import type { ComposeOption, EChartsType } from 'echarts/core'
import * as echarts from 'echarts/core'
import type { LineSeriesOption } from 'echarts/charts'
import { LineChart } from 'echarts/charts'
import type {
  DatasetComponentOption,
  GridComponentOption,
  LegendComponentOption,
  TitleComponentOption,
  TooltipComponentOption
} from 'echarts/components'
import { DatasetComponent, GridComponent, LegendComponent, TitleComponent, TooltipComponent, TransformComponent } from 'echarts/components'
import { LabelLayout, UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import { CSSProperties, ReactElement, useCallback, useEffect, useRef } from 'react'
import { chartFontSize } from '@/utils/rem.ts'

// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type MyLineOption = ComposeOption<
  LineSeriesOption | TitleComponentOption | TooltipComponentOption | GridComponentOption | DatasetComponentOption | LegendComponentOption
>

// 注册必须的组件
echarts.use([
  TitleComponent,
  LegendComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent,
  LineChart,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer
])

const MyLineChart = ({
  option,
  lineData = [],
  domStyle,
  children
}: {
  option?: MyLineOption
  lineData: Array<{
    name: string
    data: Array<{
      name: string
      value: number
    }>
  }>
  domStyle?: CSSProperties
  children?: ReactElement
}) => {
  const domRef = useRef<HTMLDivElement>(null)
  const chartRef = useRef<EChartsType>()
  const chartStyle: CSSProperties = {
    width: '100%',
    minHeight: '50px',
    height: '100%',
    position: 'relative',
    ...domStyle
  }
  const colors = ['#2080F0', '#0CB7B6']
  const chartOption: MyLineOption = {
    color: colors,
    grid: {
      top: chartFontSize(14),
      left: chartFontSize(40),
      right: chartFontSize(30),
      bottom: chartFontSize(60)
    },
    xAxis: {
      type: 'category',
      axisTick: {
        show: false
      },
      data: lineData.reduce((acc, item) => [...new Set([...item.data.map((it) => it.name), ...acc])], [] as string[])
    },
    yAxis: {
      type: 'value',
      splitLine: {
        lineStyle: {
          type: 'dashed'
        }
      }
    },
    legend: {
      show: true,
      bottom: chartFontSize(4),
      left: 'center',
      orient: 'horizontal',
      icon: 'circle',
      itemHeight: chartFontSize(10)
    },
    tooltip: {
      trigger: 'item'
    },
    series: lineData.map((line, index) => ({
      name: line.name,
      type: 'line',
      areaStyle: {
        opacity: 0.35,
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          {
            offset: 0,
            color: `${colors[index]}ff`
          },
          {
            offset: 1,
            color: `${colors[index]}00`
          }
        ])
      },
      smooth: true,
      emphasis: {
        label: {
          show: false
        }
      },
      data: line.data
    })),
    ...option
  }

  const resizeMyChart = useCallback(() => {
    chartRef.current?.resize()
  }, [])

  useEffect(() => {
    if (domRef.current) {
      chartRef.current = echarts.getInstanceByDom(domRef.current)
      if (!chartRef.current) {
        chartRef.current = echarts.init(domRef.current)
      }
      if (chartOption) chartRef.current?.setOption(chartOption)
    }
    window.addEventListener('resize', resizeMyChart)
    return () => {
      window.removeEventListener('resize', resizeMyChart)
    }
  }, [chartOption, resizeMyChart])

  return (
    <div
      style={{
        height: '100%',
        width: '100%',
        position: 'relative'
      }}>
      <div ref={domRef} style={chartStyle} />
      {children}
    </div>
  )
}

export default MyLineChart
